﻿using System;
using System.Collections.Generic;

namespace Aeon.Emulator.Dos.VirtualFileSystem
{
    /// <summary>
    /// Collection of drives on an emulated file system.
    /// </summary>
    public sealed class DriveList : IList<VirtualDrive>
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the DriveList class.
        /// </summary>
        internal DriveList()
        {
            for(int i = 0; i < this.drives.Length; i++)
                this.drives[i] = new VirtualDrive();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets the number of drives.
        /// </summary>
        public int Count
        {
            get { return this.drives.Length; }
        }
        /// <summary>
        /// Gets a value indicating whether the collection is read-only.
        /// </summary>
        bool ICollection<VirtualDrive>.IsReadOnly
        {
            get { return true; }
        }
        #endregion

        #region Public Indexers
        /// <summary>
        /// Gets the drive at the specified index.
        /// </summary>
        /// <param name="index">Index of drive to return.</param>
        /// <returns>Drive with the specified index.</returns>
        public VirtualDrive this[int index]
        {
            get
            {
                return this.drives[index];
            }
        }
        /// <summary>
        /// Gets the drive with the specified letter.
        /// </summary>
        /// <param name="letter">Letter of drive to return.</param>
        /// <returns>Drive with the specified letter.</returns>
        [Obsolete]
        public VirtualDrive this[char letter]
        {
            get
            {
                var driveLetter = char.ToUpperInvariant(letter);
                if(driveLetter < 'A' || driveLetter > 'Z')
                    throw new ArgumentOutOfRangeException("letter");

                return this.drives[(int)driveLetter - (int)'A'];
            }
        }
        /// <summary>
        /// Gets the drive with the specified letter.
        /// </summary>
        /// <param name="letter">Letter of drive to return.</param>
        /// <returns>Drive with the specified letter.</returns>
        public VirtualDrive this[DriveLetter letter]
        {
            get { return this.drives[letter.Index]; }
        }
        /// <summary>
        /// Gets the drive at the specified index.
        /// </summary>
        /// <param name="index">Index of drive to return.</param>
        /// <returns>Drive with the specified index.</returns>
        VirtualDrive IList<VirtualDrive>.this[int index]
        {
            get
            {
                return this.drives[index];
            }
            set
            {
                throw new NotSupportedException();
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns the index of a drive in the list.
        /// </summary>
        /// <param name="item">Drive whose index is returned.</param>
        /// <returns>Index of the specified drive.</returns>
        int IList<VirtualDrive>.IndexOf(VirtualDrive item)
        {
            return Array.IndexOf<VirtualDrive>(this.drives, item);
        }
        /// <summary>
        /// Not supported.
        /// </summary>
        /// <param name="index">Not supported.</param>
        /// <param name="item">Not supported.</param>
        void IList<VirtualDrive>.Insert(int index, VirtualDrive item)
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// Not supported.
        /// </summary>
        /// <param name="index">Not supported.</param>
        void IList<VirtualDrive>.RemoveAt(int index)
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// Not supported.
        /// </summary>
        /// <param name="item">Not supported.</param>
        void ICollection<VirtualDrive>.Add(VirtualDrive item)
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// Not supported.
        /// </summary>
        void ICollection<VirtualDrive>.Clear()
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// Returns a value indicating whether a drive is contained in the list.
        /// </summary>
        /// <param name="item">Drive to search for.</param>
        /// <returns>Value indicating whether the drive was found.</returns>
        bool ICollection<VirtualDrive>.Contains(VirtualDrive item)
        {
            return Array.IndexOf<VirtualDrive>(this.drives, item) >= 0;
        }
        /// <summary>
        /// Copies the collection to an array.
        /// </summary>
        /// <param name="array">Array into which drives are copied.</param>
        /// <param name="arrayIndex">Index in array to start copying.</param>
        void ICollection<VirtualDrive>.CopyTo(VirtualDrive[] array, int arrayIndex)
        {
            this.drives.CopyTo(array, arrayIndex);
        }
        /// <summary>
        /// Not supportd.
        /// </summary>
        /// <param name="item">Not supported.</param>
        /// <returns>Not supported.</returns>
        bool ICollection<VirtualDrive>.Remove(VirtualDrive item)
        {
            throw new NotSupportedException();
        }
        /// <summary>
        /// Returns an enumerator for the collection of drives.
        /// </summary>
        /// <returns>Enumerator for the collection of drives.</returns>
        public IEnumerator<VirtualDrive> GetEnumerator()
        {
            return Array.AsReadOnly(drives).GetEnumerator();
        }
        /// <summary>
        /// Returns an enumerator for the collection of drives.
        /// </summary>
        /// <returns>Enumerator for the collection of drives.</returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        #endregion

        #region Private Fields
        /// <summary>
        /// Array used to store the collection of drives.
        /// </summary>
        private readonly VirtualDrive[] drives = new VirtualDrive[26];
        #endregion
    }
}
